﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Mime
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;

    using Phuse.IO;

    /// <summary>Represents an entity body (see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a> 2.4. &amp;
    /// 2.6.) that contains a message (see <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> 5.2.).</summary>
    /// <threadsafety static="true" instance="false"/>
    public sealed class MessageBody : Body<MessageBody>
    {
        private Message content = new Message();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>Initializes a new instance of the <see cref="MessageBody"/> class.</summary>
        /// <param name="subtype">The subtype of the message body, usually one of the <see cref="MessageSubtypeNames"/>
        /// members.</param>
        /// <exception cref="ArgumentException"><paramref name="subtype"/> is <c>null</c> or empty.</exception>
        public MessageBody(string subtype) : base(subtype)
        {
        }

        /// <summary>Gets or sets the body content.</summary>
        /// <exception cref="ArgumentNullException">Attempted to set to <c>null</c>.</exception>
        /// <remarks>The default value is an empty <see cref="Message"/> object (one with neither header fields nor a
        /// body), which is set during construction and when the parser does not find a valid message.</remarks>
        public Message Content
        {
            get
            {
                return this.content;
            }

            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }

                this.content = value;
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>See <see cref="Body.WriteTo(Stream, Action{IEnumerable{HeaderField}, bool})"/>.</summary>
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Not callable from external code, CA bug?")]
        protected internal sealed override void WriteTo(
            Stream stream, Action<IEnumerable<HeaderField>, bool> writeHeaderFieldsCallback)
        {
            var fields = this.GetRequiredHeaderFields(
                MediaTypeNames.Message, new KeyValuePair<string, string>[0], ContentTransferEncodingNames.SevenBit);
            writeHeaderFieldsCallback(fields, (this.content.Body != null) || (this.content.Fields.Count > 0));

            if (stream != null)
            {
                this.content.WriteTo(stream);
            }
        }
    }
}
